
#include "syntax_tree.h"
#include "semantic_analyzer.h"
#include "semantics_expression.h"
#include "semantics_class.h"
#include "semantics_method.h"
#include "lexic_unit.h"
#include "main_container.h"
#include "errors_warnings.h"
extern MainContainer * CompilerData;



// Gr_ClassDefinition__ClassMods_TemplateDefinition_class_NAME_ClassInherit_spLCBrac_UsingDirectives_ClassBodyAdd_spRCBrac
SemanticsClass * SemanticAnalyzer::GatherFromClass(SyntaxTreeNode * nodeClass, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromClass");
#endif

	if(nodeClass->LexUnitID == -1 && nodeClass->Production == Gr_MainDefinition__ClassDefinition)
	{
		SemanticsClass * sc = GatherFromClass(nodeClass->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromClass");
#endif
		return sc;
	}
	
	if(nodeClass->LexUnitID == -1 && nodeClass->Production == Gr_ClassBody__ClassDefinition)
	{
		SemanticsClass * sc = GatherFromClass(nodeClass->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromClass");
#endif
		return sc;
	}


	SemanticsClass *sc;
	sc = new SemanticsClass();
	
	if(nodeClass->LexUnitID == -1 && nodeClass->Production == Gr_ClassDefinition__ClassMods_TemplateDefinition_class_NAME_ClassInherit_spLCBrac_UsingDirectives_ClassBodyAdd_spRCBrac)
	{
		SyntaxTreeNode * classModsNode = nodeClass->Nodes->GetData(0);

		if(classModsNode->LexUnitID == -1 && classModsNode->Production == Gr_ClassMods__ClassMod_ClassMods)
		{
			for(int i = 0; i < classModsNode->Nodes->GetCount(); i++)
			{
				// <class_mods> ~ <class_mod> <class_mods>
				SyntaxTreeNode * classModNode = classModsNode->Nodes->GetData(i);

				// Check if modifiers are written at most once and collect them...
				if(classModNode->LexUnitID == -1 && classModNode->Production == Gr_ClassMod__abstract)
				{
					if(sc->ModifierAbstract == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(classModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_ABSTRACT);
					}
					else
					{
						sc->ModifierAbstract = true;
					}
				}
				else if(classModNode->LexUnitID == -1 && classModNode->Production == Gr_ClassMod__public)
				{
					if(sc->ModifierPublic == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(classModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PUBLIC);
					}
					else
					{
						sc->ModifierPublic = true;
					}
				}
				else if(classModNode->LexUnitID == -1 && classModNode->Production == Gr_ClassMod__private)
				{
					if(sc->ModifierPrivate == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(classModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PRIVATE);
					}
					else
					{
						sc->ModifierPrivate = true;
					}
				}
				else if(classModNode->LexUnitID == -1 && classModNode->Production == Gr_ClassMod__protected)
				{
					if(sc->ModifierProtected)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(classModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PROTECTED);
					}
					else
					{	
						sc->ModifierProtected = true;
					}
				}
				else if(classModNode->LexUnitID == -1 && classModNode->Production == Gr_ClassMod__final)
				{
					if(sc->ModifierFinal)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(classModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_FINAL);
					}
					else
					{
						sc->ModifierFinal = true;
					}
				}
			}
		}
		

		SyntaxTreeNode * templateDefinitionNode = nodeClass->Nodes->GetData(1);
		if(templateDefinitionNode->LexUnitID == -1 && templateDefinitionNode->Production == Gr_TemplateDefinition__template_TemplateUse)
		{
			// <template_definition> ~ template <template_use>
			SyntaxTreeNode * templateUseNode = templateDefinitionNode->Nodes->GetData(1);

			// <template_use> ~ < <templates_list> > 
			SyntaxTreeNode * templatesListNode = templateUseNode->Nodes->GetData(1);

			// TODO - collect all names
			
			// #####
			// <templates_list> ~ NAME <templates_list_add>
			SyntaxTreeNode * nameNode = templatesListNode->Nodes->GetData(0);
			SyntaxTreeNode * tempNode = templatesListNode->Nodes->GetData(1);

			sc->TemplateNames->Add(GatherFromNameNode(nameNode)->GetData(0));

			// "tempNode" is a workaround
			for(int j = 0; tempNode && j < tempNode->Nodes->GetCount(); j++)
//			for(int j = 0; tempCommaNameNode && j < tempCommaNameNode->Nodes->GetCount(); j++)
			//while(tempNode && tempNode->LexUnitID == -1 && tempNode->Production == Gr_TemplatesListAdd__NameCommaAdd_TemplatesListAdd)
			{
				if(tempNode->Nodes->GetData(j))
				{
					sc->TemplateNames->Add(GatherFromNameNode(tempNode->Nodes->GetData(j)->Nodes->GetData(1))->GetData(0));
				}

				//tempNode = tempNode->Nodes->GetData(1);
			}
			
			sc->HasTemplate = true;
			
		}

		SyntaxTreeNode * nameNode = nodeClass->Nodes->GetData(3);

		sc->Name = GatherFromNameNode(nameNode);
		
		SyntaxTreeNode * classInheritNode = nodeClass->Nodes->GetData(4);
		if(classInheritNode->LexUnitID == -1 && classInheritNode->Production == Gr_ClassInherit__spColon_ClassInheritName)
		{
			
			// ######
			// <class_inherit> ~ : <class_inherit_name>
			SyntaxTreeNode * classInheritNameNode = classInheritNode->Nodes->GetData(1);
			
			// <class_inherit_name> ~ <class_mods> <name> <template_use>
			SyntaxTreeNode * nameNode = classInheritNameNode->Nodes->GetData(0);
	
			sc->InheritName = GatherFromNameNode(nameNode);
			
		}


		SyntaxTreeNode * usingDirectivesNode = nodeClass->Nodes->GetData(6);
		int currentContext = SaveContext(GetCurrentContext(usingDirectivesNode), parentContext);
		
		SyntaxTreeNode * classBodyAddNode = nodeClass->Nodes->GetData(7);

		if(classBodyAddNode->LexUnitID == -1 && classBodyAddNode->Production == Gr_ClassBodyAdd__ClassBody_ClassBodyAdd)
		{
			for(int i = 0; i < classBodyAddNode->Nodes->GetCount(); i++)
			{
				SyntaxTreeNode * classBodyNode = classBodyAddNode->Nodes->GetData(i);

				if(classBodyNode->LexUnitID == -1 && classBodyNode->Production == Gr_ClassBody__ConstructorDefinition)
				{
					sc->Methods->Add(GatherFromMethod(classBodyNode, currentContext));
				}
				else if(classBodyNode->LexUnitID == -1 && classBodyNode->Production == Gr_ClassBody__FieldDefinition)
				{
					sc->Fields->Add(GatherFromField(classBodyNode, currentContext));
				}
				else if(classBodyNode->LexUnitID == -1 && classBodyNode->Production == Gr_ClassBody__MethodDefinition)
				{
					sc->Methods->Add(GatherFromMethod(classBodyNode, currentContext));
				}
				else if(classBodyNode->LexUnitID == -1 && classBodyNode->Production == Gr_ClassBody__PropertyDefinition)
				{
					sc->Properties->Add(GatherFromProperty(classBodyNode, currentContext));
				}
				else if(classBodyNode->LexUnitID == -1 && classBodyNode->Production == Gr_ClassBody__EnumDefinition)
				{
					sc->Enums->Add(GatherFromEnum(classBodyNode, currentContext));
				}
				else if(classBodyNode->LexUnitID == -1 && classBodyNode->Production == Gr_ClassBody__ClassDefinition)
				{
					sc->Classes->Add(GatherFromClass(classBodyNode, currentContext));
				}
				else
				{
					// report error
					CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(classBodyNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
				}
			}
		}	

	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeClass->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromClass");
#endif
	return sc;
}



// Gr_ConstructorDefinition__ConstrMod_NAME_spLPar_Parameters_spRPar_ConstrInherit_ConstrBody
// Gr_MethodDefinition__MethodMods_StartProcess_DataType_NAME_spLPar_Parameters_spRPar_MethodBodyDecl
// Gr_MethodDefinition__MethodMods_numeric_NumericMod_DataType_NAME_spLPar_Parameters_spRPar_spLCBrac_InfBegin_ValuePairs_InfEnd_spRCBrac
SemanticsMethod * SemanticAnalyzer::GatherFromMethod(SyntaxTreeNode * nodeMethod, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromMethod");
#endif

	if(nodeMethod->LexUnitID == -1 && nodeMethod->Production == Gr_MainDefinition__MethodDefinition)
	{
		SemanticsMethod * sm = GatherFromMethod(nodeMethod->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromMethod");
#endif
		return sm;
	}

	if(nodeMethod->LexUnitID == -1 && nodeMethod->Production == Gr_ClassBody__ConstructorDefinition)
	{
		SemanticsMethod * sm = GatherFromMethod(nodeMethod->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromMethod");
#endif
		return sm;
	}
	
	if(nodeMethod->LexUnitID == -1 && nodeMethod->Production == Gr_ClassBody__MethodDefinition)
	{
		SemanticsMethod * sm = GatherFromMethod(nodeMethod->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromMethod");
#endif
		return sm;
	}


	SemanticsMethod *sm;
	sm = new SemanticsMethod();

	if(nodeMethod->LexUnitID == -1 && nodeMethod->Production == Gr_ConstructorDefinition__ConstrMod_NAME_spLPar_Parameters_spRPar_ConstrInherit_ConstrBody)
	{
		sm->IsConstructor = true;
		
		SyntaxTreeNode * constrModNode = nodeMethod->Nodes->GetData(0);
		if(constrModNode->Production == Gr_ConstrMod__public)
		{
			sm->ModifierPublic = true;
		}
		else if(constrModNode->Production == Gr_ConstrMod__private)
		{
			sm->ModifierPrivate = true;
		}
		else if(constrModNode->Production == Gr_ConstrMod__protected)
		{
			sm->ModifierProtected = true;
		}

		
		
		SyntaxTreeNode * parametersNode = nodeMethod->Nodes->GetData(3);

		// TODO - only check this
		delete sm->Parameters;
		sm->Parameters = ReadMethodParameters(parametersNode);


		SyntaxTreeNode * constrInheritNode = nodeMethod->Nodes->GetData(5);
		if(constrInheritNode->LexUnitID == -1 && constrInheritNode->Production == Gr_ConstrInherit__spColon_Name_spLPar_Arguments_spRPar)
		{
			// <constr_inherit> ~ : <name> ( <arguments> )  {:}
			SyntaxTreeNode * nameNode = constrInheritNode->Nodes->GetData(1);
			sm->ConstructorInherit->Name = GatherFromNameNode(nameNode);

			
			// <arguments> ~ <expression> <arguments_add>
			// <arguments> ~ ? {)}
			SyntaxTreeNode * argumentsNode = constrInheritNode->Nodes->GetData(3);

			SyntaxTreeNode * expressionNode = argumentsNode->Nodes->GetData(0);

			// If there's anything, parse it...
			if(expressionNode != NULL)
			{
				sm->ConstructorInherit->Arguments->Add(GatherFromExpression(expressionNode));
			}


			if(argumentsNode->LexUnitID == -1 && argumentsNode->Production != Gr_Arguments__epsilon)
			{

				// <arguments_add> ~ <argument_comma_add> <arguments_add>
				// <arguments_add> ~ ?
				// <argument_comma_add> ~ , <expression>
				SyntaxTreeNode * argumentsAddNodeFirst = argumentsNode->Nodes->GetData(1);

				for(int i = 0; i < argumentsAddNodeFirst->Nodes->GetCount(); i++)
				{
					SyntaxTreeNode * argumentsAddNode = argumentsAddNodeFirst->Nodes->GetData(i);
					//SyntaxTreeNode * expressionNode = argumentsNode->Nodes->GetData(0);
					SyntaxTreeNode * expressionNode = argumentsAddNode->Nodes->GetData(1);
				
					sm->ConstructorInherit->Arguments->Add(GatherFromExpression(expressionNode));
				}
/*
				SyntaxTreeNode * argumentsAddNode = argumentsNode->Nodes->GetData(1);
				while(argumentsAddNode->LexUnitID == -1 && argumentsAddNode->Production != Gr_ArgumentsAdd__epsilon)
				{
					// <arguments_add> ~ <argument_comma_add> <arguments_add>
					// <argument_comma_add> ~ , <expression>
					SyntaxTreeNode * argumentCommaAddNode = argumentsAddNode->Nodes->GetData(0);
					expressionNode = argumentCommaAddNode->Nodes->GetData(1);
					sm->ConstructorInherit->Arguments->Add(GatherFromExpression(expressionNode));

					argumentsAddNode = argumentsAddNode->Nodes->GetData(1);
				}
				*/
			}

		}

		SyntaxTreeNode * constrBodyNode = nodeMethod->Nodes->GetData(6);

		
		if(constrBodyNode->LexUnitID == -1 && constrBodyNode->Production == Gr_ConstrBody__spLCBrac_MethodBody_spRCBrac)
		{
			/*
			SyntaxTreeNode * methodStatementsNode = constrBodyNode->Nodes->GetData(1);
			for(int i = 0; i < methodStatementsNode->Nodes->GetCount(); i++)
			{
				sm->MethodBody->Body->Add(ReadMethodStatement(methodStatementsNode->Nodes->GetData(i)));
			}
			*/

			// TODO method body
		}
		
	}
	else if(nodeMethod->LexUnitID == -1 && nodeMethod->Production == Gr_MethodDefinition__MethodMods_StartProcess_DataType_NAME_spLPar_Parameters_spRPar_MethodBodyDecl)
	{
		SyntaxTreeNode * methodModsNode = nodeMethod->Nodes->GetData(0);

		if(methodModsNode->LexUnitID == -1 && methodModsNode->Production == Gr_MethodMods__MethodMod_MethodMods)
		{
			for(int i=0; i < methodModsNode->Nodes->GetCount(); i++)
			{
				SyntaxTreeNode * methodModNode = methodModsNode->Nodes->GetData(i);

				if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__abstract)
				{
					if(sm->ModifierAbstract == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_ABSTRACT);
					}
					else
					{
						sm->ModifierAbstract = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__virtual)
				{
					if(sm->ModifierVirtual == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_VIRTUAL);
					}
					else
					{
						sm->ModifierVirtual = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__public)
				{
					if(sm->ModifierPublic == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PUBLIC);
					}
					else
					{
						sm->ModifierPublic = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__private)
				{
					if(sm->ModifierPrivate == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PRIVATE);
					}
					else
					{
						sm->ModifierPrivate = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__protected)
				{
					if(sm->ModifierProtected == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PROTECTED);
					}
					else
					{
						sm->ModifierProtected = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__override)
				{
					if(sm->ModifierOverride == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_OVERRIDE);
					}
					else
					{
						sm->ModifierOverride = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__static)
				{
					if(sm->ModifierStatic == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_STATIC);
					}
					else
					{
						sm->ModifierStatic = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__final)
				{
					if(sm->ModifierFinal == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_FINAL);
					}
					else
					{
						sm->ModifierFinal = true;
					}
				}
			}
		}


		SyntaxTreeNode * dataTypeNode = nodeMethod->Nodes->GetData(2);
		sm->DataType = GatherFromDataType(dataTypeNode);

		SyntaxTreeNode * methodNameNode = nodeMethod->Nodes->GetData(3);
		sm->Name = GatherFromNameNode(methodNameNode);

		SyntaxTreeNode * parametersNode = nodeMethod->Nodes->GetData(5);

		// TODO - only check this
		delete sm->Parameters;
		sm->Parameters = ReadMethodParameters(parametersNode);

		SyntaxTreeNode * methodBodyDeclNode = nodeMethod->Nodes->GetData(7);
		/*
		for(int i = 0; i < methodBodyDeclNode->Nodes->GetCount(); i++)
		{
			sm->MethodBody->Body->Add(ReadMethodBody(methodBodyDeclNode->Nodes->GetData(i)));
		}
		*/
		/*
			TODO - which one is the right one
		*/
		if(sm->MethodBody != NULL)
		{
			delete sm->MethodBody;
			sm->MethodBody = NULL;
		}

		sm->MethodBody = ReadMethodBody(methodBodyDeclNode);
	}
	else if(nodeMethod->LexUnitID == -1 && nodeMethod->Production == Gr_MethodDefinition__MethodMods_numeric_NumericMod_DataType_NAME_spLPar_Parameters_spRPar_spLCBrac_InfBegin_ValuePairs_InfEnd_spRCBrac)
	{
		sm->IsNumeric = true;
		SyntaxTreeNode * methodModsNode = nodeMethod->Nodes->GetData(0);

		if(methodModsNode->Production == Gr_MethodMods__MethodMod_MethodMods)
		{
			for(int i=0; i < methodModsNode->Nodes->GetCount(); i++)
			{
				SyntaxTreeNode * methodModNode = methodModsNode->Nodes->GetData(i);

				if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__abstract)
				{
					if(sm->ModifierAbstract == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_ABSTRACT);
					}
					else
					{
						sm->ModifierAbstract = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__virtual)
				{
					if(sm->ModifierVirtual == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_VIRTUAL);
					}
					else
					{
						sm->ModifierVirtual = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__public)
				{
					if(sm->ModifierPublic == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PUBLIC);
					}
					else
					{
						sm->ModifierPublic = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__private)
				{
					if(sm->ModifierPrivate == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PRIVATE);
					}
					else
					{
						sm->ModifierPrivate = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__protected)
				{
					if(sm->ModifierProtected == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PROTECTED);
					}
					else
					{
						sm->ModifierProtected = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__override)
				{
					if(sm->ModifierOverride == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_OVERRIDE);
					}
					else
					{
						sm->ModifierOverride = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__static)
				{
					if(sm->ModifierStatic == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_STATIC);
					}
					else
					{
						sm->ModifierStatic = true;
					}
				}
				else if(methodModNode->LexUnitID == -1 && methodModNode->Production == Gr_MethodMod__final)
				{
					if(sm->ModifierFinal == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(methodModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_FINAL);
					}
					else
					{
						sm->ModifierFinal = true;
					}
				}
			}
		}

		SyntaxTreeNode * numericModNode = nodeMethod->Nodes->GetData(2);
		if(numericModNode->LexUnitID == -1 && numericModNode->Production == Gr_NumericMod__continuous)
		{
			sm->IsContinuous = true;
		}
		else if(numericModNode->LexUnitID == -1 && numericModNode->Production == Gr_NumericMod__discrete)
		{
			sm->IsDiscrete = true;
		}

		SyntaxTreeNode * dataTypeNode = nodeMethod->Nodes->GetData(3);
		sm->DataType = GatherFromDataType(dataTypeNode);


		SyntaxTreeNode * methodNameNode = nodeMethod->Nodes->GetData(4);
		sm->Name = GatherFromNameNode(methodNameNode);


		SyntaxTreeNode * parametersNode = nodeMethod->Nodes->GetData(6);

		// TODO - only check this
		delete sm->Parameters;
		sm->Parameters = ReadMethodParameters(parametersNode);

		
		SyntaxTreeNode * infBeginNode = nodeMethod->Nodes->GetData(9);
		if(infBeginNode->LexUnitID == -1 && infBeginNode->Production == Gr_InfBegin__opSub_INF_spSemiCol)
		{
			sm->HasMinusINF;
		}

		SyntaxTreeNode * valuePairsNode = nodeMethod->Nodes->GetData(10);
		for(int i = 0; i < valuePairsNode->Nodes->GetCount(); i++)
		{
			sm->ValuePairs->Add(ReadMethodValuePair(valuePairsNode->Nodes->GetData(i)));
		}

		SyntaxTreeNode * infEndNode = nodeMethod->Nodes->GetData(11);
		if(infEndNode->LexUnitID == -1 && infEndNode->Production == Gr_InfEnd__spSemiCol_opAdd_INF)
		{
			sm->HasPlusINF = true;
		}
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeMethod->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromMethod");
#endif
	return sm;
}

GenericTable<SemanticsMethodParameter> * SemanticAnalyzer::ReadMethodParameters(SyntaxTreeNode * msParametersNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMethodParameters");
#endif

	GenericTable<SemanticsMethodParameter> * smpTable = new GenericTable<SemanticsMethodParameter>();

	// TODO	
	// <parameters> ~ <parameter> <parameters_add>
	// <parameters> ~ ? {)}
	if(msParametersNode->LexUnitID == -1 && msParametersNode->Production == Gr_Parameters__Parameter_ParametersAdd)
	{
		SyntaxTreeNode * parameterNode = msParametersNode->Nodes->GetData(0);
		SemanticsMethodParameter * smp = ReadMethodParameter(parameterNode);
		
		// if there was anything, add it to the table...
		if(smp != NULL)
		{
			smpTable->Add(smp);
		}

		// <parameters_add> ~ <parameter_comma_add> <parameters_add>  {,}
		// <parameter_comma_add> ~ , <parameter>  {,}
		// <parameters_add> ~ ? {)}
		SyntaxTreeNode * parametersAddNode = msParametersNode->Nodes->GetData(1);

		for(int i = 0; i < parametersAddNode->Nodes->GetCount(); i++)
		{
			SyntaxTreeNode * parameterCommaAddNode = parametersAddNode->Nodes->GetData(i);

			if(parameterCommaAddNode->LexUnitID == -1 && parameterCommaAddNode->Production == Gr_ParameterCommaAdd__spComma_Parameter)
			{
				parameterNode = parameterCommaAddNode->Nodes->GetData(1);

				// if there was anything, add it to the table...
				if((smp = ReadMethodParameter(parameterNode)) != NULL)
				{
					smpTable->Add(smp);
				}
			}
			else
			{
				// report error
				CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(parameterCommaAddNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
			}
		}
		/*
		while(parametersAddNode->LexUnitID == -1 && parametersAddNode->Production == Gr_ParametersAdd__ParameterCommaAdd_ParametersAdd)
		{
			SyntaxTreeNode * parameterCommaAddNode = parametersAddNode->Nodes->GetData(0);
			parameterNode = parameterCommaAddNode->Nodes->GetData(1);

			if(parameterNode->LexUnitID == -1 && parameterNode->Production == Gr_Parameter__DataType_NAME_ArrayDefinitions)
			{
				// if there was anything, add it to the table...
				if((smp = ReadMethodParameter(parameterNode)) != NULL)
				{
					smpTable->Add(smp);
				}
			}
			else
			{
				// report error
				CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(parameterNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
			}

			parametersAddNode = parametersAddNode->Nodes->GetData(1);
		}
		*/
	}
	else if(msParametersNode->LexUnitID == -1 && msParametersNode->Production == Gr_Parameters__epsilon)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportExit("ReadMethodParameters");
#endif
		return smpTable;
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(msParametersNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMethodParameters");
#endif
	return smpTable;
}


// Gr_Parameters__Parameter_ParametersAdd
SemanticsMethodParameter * SemanticAnalyzer::ReadMethodParameter(SyntaxTreeNode * msParameterNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMethodParameter");
#endif
	SemanticsMethodParameter * smp = new SemanticsMethodParameter();
	
	if(msParameterNode->LexUnitID == -1 && msParameterNode->Production == Gr_Parameter__DataType_NAME_ArrayDefinitions)
	{
		SyntaxTreeNode * dataTypeNode = msParameterNode->Nodes->GetData(0);
		smp->DataType = GatherFromDataType(dataTypeNode);

		SyntaxTreeNode * nameNode = msParameterNode->Nodes->GetData(1);
		smp->Name = GatherFromNameNode(nameNode);

		// TODO array definitions
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(msParameterNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMethodParameter");
#endif
	return smp;
}


// Gr_ValuePairs__ValuePair_ValuePairsAdds
SemanticsMethodValuePair * SemanticAnalyzer::ReadMethodValuePair(SyntaxTreeNode * msValuePair)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadMethodValuePair");
#endif
	SemanticsMethodValuePair * smvp = new SemanticsMethodValuePair();
	
	// <value_pairs> ~ <value_pair> <value_pairs_adds> 
	// <value_pairs> ~ ?
	if(msValuePair->LexUnitID == -1 && msValuePair->Production == Gr_ValuePair__SignValue_LITERAL_spArrow_SignValue_LITERAL)
	{
//		SyntaxTreeNode * valuePairNode = msValuePair->Nodes->GetData(0);
		SyntaxTreeNode * valuePairNode = msValuePair;
		
		// <value_pair> ~ <sign_value> LITERAL -> <sign_value> LITERAL  {+, -, LITERAL}
/*		
		if(valuePairNode->Production == Gr_ValuePair__SignValue_LITERAL_spArrow_SignValue_LITERAL)
		{
*/
			SyntaxTreeNode * signValueNode = valuePairNode->Nodes->GetData(0);
			if(signValueNode->Production == Gr_SignValue__opSub) smvp->minusParameterSign = true;
		
			SyntaxTreeNode * literalNode = valuePairNode->Nodes->GetData(1);
			smvp->Parameter = literalNode->LexUnitID;
			
			signValueNode = valuePairNode->Nodes->GetData(3);
			if(signValueNode->Production == Gr_SignValue__opSub) smvp->minusValueSign = true;

			literalNode = valuePairNode->Nodes->GetData(4);
			smvp->Value = literalNode->LexUnitID;
/*
		}
*/

		// <value_pairs_adds> ~ <value_pair_add> <value_pairs_adds>
		// <value_pair_add> ~ ; <value_pair> 
		// <value_pairs_adds> ~ ?

		/*
		SyntaxTreeNode * valuePairsAddsNode = msValuePair->Nodes->GetData(1);
		while(valuePairsAddsNode->Production != Gr_ValuePairsAdds__epsilon)
		{
			SyntaxTreeNode * valuePairAddNode = valuePairsAddsNode->Nodes->GetData(0);
			valuePairNode = valuePairAddNode->Nodes->GetData(1);
			if(valuePairNode->Production == Gr_ValuePair__SignValue_LITERAL_spArrow_SignValue_LITERAL)
			{
				SyntaxTreeNode * signValueNode = valuePairNode->Nodes->GetData(0);
				if(signValueNode->Production == Gr_SignValue__opSub) smvp->minusParameterSign = true;
		
				SyntaxTreeNode * literalNode = valuePairNode->Nodes->GetData(1);
				smvp->Parameter = literalNode->LexUnitID;
			
				signValueNode = valuePairNode->Nodes->GetData(3);
				if(signValueNode->Production == Gr_SignValue__opSub) smvp->minusValueSign = true;

				literalNode = valuePairNode->Nodes->GetData(4);
				smvp->Value = literalNode->LexUnitID;
			}
			valuePairsAddsNode = valuePairsAddsNode->Nodes->GetData(1);
		}
		*/
		
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("ReadMethodValuePair");
#endif

	return smvp;
}



// Gr_FieldDefinition__FieldMods_TracePart_DataType_FieldNames_spSemiCol
SemanticsField * SemanticAnalyzer::GatherFromField(SyntaxTreeNode * nodeField, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromField");
#endif

	if(nodeField->LexUnitID == -1 && nodeField->Production == Gr_MainDefinition__FieldDefinition)
	{
		SemanticsField * sf = GatherFromField(nodeField->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromField");
#endif

		return sf;
	}


	if(nodeField->LexUnitID == -1 && nodeField->Production == Gr_ClassBody__FieldDefinition)
	{
		SemanticsField * sf = GatherFromField(nodeField->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromField");
#endif

		return sf;
	}


	SemanticsField *sf;
	sf = new SemanticsField();

	if(nodeField->LexUnitID == -1 && nodeField->Production == Gr_FieldDefinition__FieldMods_TracePart_DataType_FieldNames_spSemiCol)
	{
		SyntaxTreeNode * fieldModsNode = nodeField->Nodes->GetData(0);

		if(fieldModsNode->Production == Gr_FieldMods__FieldMod_FieldMods)
		{
			for(int i = 0; i < fieldModsNode->Nodes->GetCount(); i++)
			{
				SyntaxTreeNode * fieldModNode = fieldModsNode->Nodes->GetData(i);

				if(fieldModNode->LexUnitID == -1 && fieldModNode->Production == Gr_FieldMod__const)
				{
					if(sf->ModifierConst == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(fieldModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_CONST);
					}
					else
					{
						sf->ModifierConst = true;
					}
				}
				else if(fieldModNode->LexUnitID == -1 && fieldModNode->Production == Gr_FieldMod__public)
				{
					if(sf->ModifierPublic == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(fieldModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PUBLIC);
					}
					else
					{
						sf->ModifierPublic = true;
					}
				}
				else if(fieldModNode->LexUnitID == -1 && fieldModNode->Production == Gr_FieldMod__private)
				{
					if(sf->ModifierPrivate == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(fieldModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PRIVATE);
					}
					else
					{
						sf->ModifierPrivate = true;
					}
				}
				else if(fieldModNode->LexUnitID == -1 && fieldModNode->Production == Gr_FieldMod__protected)
				{
					if(sf->ModifierProtected == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(fieldModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PROTECTED);
					}
					else
					{
						sf->ModifierProtected = true;
					}
				}
				else if(fieldModNode->LexUnitID == -1 && fieldModNode->Production == Gr_FieldMod__static)
				{
					if(sf->ModifierStatic == true)
					{
						// report error
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(fieldModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_STATIC);
					}
					else
					{
						sf->ModifierStatic = true;
					}
				}
			}
		}
		

		SyntaxTreeNode * dataTypeNode = nodeField->Nodes->GetData(2);
		sf->DataType = GatherFromDataType(dataTypeNode);

		SyntaxTreeNode * fieldNamesNode = nodeField->Nodes->GetData(3);

		while(fieldNamesNode->LexUnitID == -1 && fieldNamesNode->Production == Gr_FieldNames__FieldName_Equals_FieldNamesAdd)
		{
			// each entry into field variable
			SemanticsFieldVariable * sfv = new SemanticsFieldVariable();

			SyntaxTreeNode * fieldNameNode = fieldNamesNode->Nodes->GetData(0);
			if(fieldNameNode->LexUnitID == -1 && fieldNameNode->Production == Gr_FieldName__NAME_ArrayDefinitions)
			{
				SyntaxTreeNode * nameNode = fieldNameNode->Nodes->GetData(0);
				sfv->Name = GatherFromNameNode(nameNode);
			}

			sfv->ArrayCount = GatherArrayDimensionsCount(fieldNameNode->Nodes->GetData(1));

			SyntaxTreeNode * equalsNode = fieldNamesNode->Nodes->GetData(1);

			if(equalsNode->LexUnitID == -1 && equalsNode->Production == Gr_Equals__opAssign_Expression)
			{
				SyntaxTreeNode * expressionNode = equalsNode->Nodes->GetData(1);
				sfv->Expression = GatherFromExpression(expressionNode);
			}

			// add each field variable to field entry...
			sf->Variables->Add(sfv);

			// go to next name in the list (if any...)
			SyntaxTreeNode * nextNode = fieldNamesNode->Nodes->GetData(2);
			if(nextNode->LexUnitID == -1 && nextNode->Production == Gr_FieldNamesAdd__spComma_FieldNames)
			{
				fieldNamesNode = nextNode->Nodes->GetData(1);
			}
			else
			{
				break;
			}
		}

	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeField->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromField");
#endif
	return sf;
}



// Gr_PropertyDefinition__PropertyMods_DataType_PropertyName
SemanticsProperty * SemanticAnalyzer::GatherFromProperty(SyntaxTreeNode * nodeProperty, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromProperty");
#endif

	if(nodeProperty->LexUnitID == -1 && nodeProperty->Production == Gr_MainDefinition__PropertyDefinition)
	{
		SemanticsProperty * sp = GatherFromProperty(nodeProperty->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromProperty");
#endif

		return sp;
	}


	if(nodeProperty->LexUnitID == -1 && nodeProperty->Production == Gr_ClassBody__PropertyDefinition)
	{
		SemanticsProperty * sp = GatherFromProperty(nodeProperty->Nodes->GetData(0), parentContext);

#ifdef TRACE
		CompilerData->LogTrace->ReportExit("GatherFromProperty");
#endif

		return sp;
	}


	SemanticsProperty *sp;
	sp = new SemanticsProperty();

	if(nodeProperty->Production == Gr_PropertyDefinition__PropertyMods_DataType_PropertyName)
	{
		SyntaxTreeNode * propertyModsNode = nodeProperty->Nodes->GetData(0);
		if(propertyModsNode->Production == Gr_PropertyMods__PropertyMod_PropertyMods)
		{
			for(int i = 0; i < propertyModsNode->Nodes->GetCount(); i++)
			{
				SyntaxTreeNode * propertyModNode = propertyModsNode->Nodes->GetData(i);

				if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__public)
				{
					if(sp->ModifierPublic == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PUBLIC);
					}
					else
					{
						sp->ModifierPublic = true;
					}
				}
				else if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__protected)
				{
					if(sp->ModifierProtected == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PROTECTED);
					}
					else
					{
						sp->ModifierProtected = true;
					}
				}
				else if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__private)
				{
					if(sp->ModifierPrivate == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_PRIVATE);
					}
					else
					{
						sp->ModifierPrivate = true;
					}
				}
				else if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__static)
				{
					if(sp->ModifierStatic == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_STATIC);
					}
					else
					{
						sp->ModifierStatic = true;
					}
				}
				else if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__abstract)
				{
					if(sp->ModifierAbstract == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_ABSTRACT);
					}
					else
					{
						sp->ModifierAbstract = true;
					}
				}
				else if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__override)
				{
					if(sp->ModifierOverride == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_OVERRIDE);
					}
					else
					{
						sp->ModifierOverride = true;
					}
				}
				else if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__virtual)
				{
					if(sp->ModifierVirtual == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_VIRTUAL);
					}
					else
					{
						sp->ModifierVirtual = true;
					}
				}
				else if(propertyModNode->LexUnitID == -1 && propertyModNode->Production == Gr_PropertyMod__final)
				{
					if(sp->ModifierFinal == true)
					{
						CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(propertyModNode->Nodes->GetData(0)->LexUnitID), ERR_SEM_MULTIPLE_MODIFIER_FINAL);
					}
					else
					{
						sp->ModifierFinal = true;
					}
				}
			}
		}


		SyntaxTreeNode * dataTypeNode = nodeProperty->Nodes->GetData(1);
		sp->DataType = GatherFromDataType(dataTypeNode);

		SyntaxTreeNode * propertyNameNode = nodeProperty->Nodes->GetData(2);
		if(propertyNameNode->LexUnitID == -1 && propertyNameNode->Production == Gr_PropertyName__NAME_PropArrayDefs_PropertyBody)
		{
			SyntaxTreeNode * nameNode = propertyNameNode->Nodes->GetData(0);
			sp->Name = GatherFromNameNode(nameNode);

			SyntaxTreeNode * propertyBodyNode = propertyNameNode->Nodes->GetData(2);

			SyntaxTreeNode * propertyReadNode;
			SyntaxTreeNode * propertyWriteNode;

			if(propertyBodyNode->LexUnitID == -1 && propertyBodyNode->Production == Gr_PropertyBody__spLCBrac_PropertyRead_PropertyWrite_spRCBrac)
			{
				propertyReadNode = propertyBodyNode->Nodes->GetData(1);
				propertyWriteNode = propertyBodyNode->Nodes->GetData(2);
			}
			else if(propertyBodyNode->LexUnitID == -1 && propertyBodyNode->Production == Gr_PropertyBody__spLCBrac_PropertyWrite_PropertyRead_spRCBrac)
			{
				propertyReadNode = propertyBodyNode->Nodes->GetData(2);
				propertyWriteNode = propertyBodyNode->Nodes->GetData(1);
			}

			if((propertyBodyNode->LexUnitID == -1 && propertyBodyNode->Production == Gr_PropertyBody__spLCBrac_PropertyRead_PropertyWrite_spRCBrac) ||
				(propertyBodyNode->LexUnitID == -1 && propertyBodyNode->Production == Gr_PropertyBody__spLCBrac_PropertyWrite_PropertyRead_spRCBrac))
			{
				if(propertyReadNode->Production == Gr_PropertyRead__read_spLCBrac_MethodBody_spRCBrac)
				{
					SyntaxTreeNode * methodBodyNode = propertyReadNode->Nodes->GetData(2);
					sp->MethodRead->MethodBody = ReadMethodBody(methodBodyNode);
				}
				if(propertyWriteNode->Production == Gr_PropertyWrite__write_spLCBrac_MethodBody_spRCBrac)
				{
					SyntaxTreeNode * methodBodyNode = propertyWriteNode->Nodes->GetData(2);
					sp->MethodWrite->MethodBody = ReadMethodBody(methodBodyNode);
				}
			}
			else
			{
				// report error
				CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeProperty->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
			}
		}
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeProperty->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromProperty");
#endif
	return sp;
}

